/*
 * @[H]:  Copyright (c) 2021 Phytium Information Technology, Inc. 
 * 
 *  SPDX-License-Identifier: Apache-2.0. 
 * 
 * @Date: 2021-07-22 16:52:13
 * @LastEditTime: 2021-07-23 20:31:58
 * @Description:  Description of file
 * @Modify History: 
 * * * Ver   Who        Date         Changes
 * * ----- ------     --------    --------------------------------------
 */

#include "f_xmac.h"
#include "f_xmac_hw.h"

/************************** Constant Definitions *****************************/

/**************************** Type Definitions *******************************/

/***************** Macros (Inline Functions) Definitions *********************/

/************************** Function Prototypes ******************************/

/************************** Variable Definitions *****************************/

/*****************************************************************************/
/**
 * Install an asynchronous handler function for the given handler_type:
 *
 * @param instance_p is a pointer to the instance to be worked on.
 * @param handler_type indicates what interrupt handler type is.
 *        FXMAC_HANDLER_DMASEND, FXMAC_HANDLER_DMARECV and
 *        FXMAC_HANDLER_ERROR.
 * @param func_pointer is the pointer to the callback function
 * @param call_back_ref is the upper layer callback reference passed back when
 *        when the callback function is invoked.
 *
 * @return
 *
 * None.
 *
 * @note
 * There is no assert on the call_back_ref since the driver doesn't know what
 * it is.
 *
 *****************************************************************************/
LONG FXmacSetHandler(FXmac *instance_p, u32 handler_type,
                     void *func_pointer, void *call_back_ref)
{
    LONG status;
    FT_ASSERTNONVOID(instance_p != NULL);
    FT_ASSERTNONVOID(func_pointer != NULL);
    FT_ASSERTNONVOID(instance_p->is_ready == (u32)FT_COMPONENT_IS_READY);

    switch (handler_type)
    {
    case FXMAC_HANDLER_DMASEND:
        status = (LONG)(FT_SUCCESS);
        instance_p->send_irq_handler = ((FXmacIrqHandler)(void *)func_pointer);
        instance_p->send_args = call_back_ref;
        break;
    case FXMAC_HANDLER_DMARECV:
        status = (LONG)(FT_SUCCESS);
        instance_p->recv_irq_handler = ((FXmacIrqHandler)(void *)func_pointer);
        instance_p->recv_args = call_back_ref;
        break;
    case FXMAC_HANDLER_ERROR:
        status = (LONG)(FT_SUCCESS);
        instance_p->error_irq_handler = ((FXmacErrorIrqHandler)(void *)func_pointer);
        instance_p->error_args = call_back_ref;
        break;
    default:
        status = (LONG)(FXMAC_ERR_INVALID_PARAM);
        break;
    }
    return status;
}

/*****************************************************************************/
/**
* Master interrupt handler for EMAC driver. This routine will query the
* status of the device, bump statistics, and invoke user callbacks.
*
* This routine must be connected to an interrupt controller using OS/BSP
* specific methods.
*
* @param FXmacPtr is a pointer to the FXmac instance that has caused the
*        interrupt.
*
******************************************************************************/
// void FXmacIntrHandler(void *args)
// {
//     u32 reg_isr;
//     u32 reg_sr;
//     u32 reg_ctrl;
//     u32 regq1_isr = 0U;
//     FXmac *instance_p = (FXmac *)args;

//     FT_ASSERTVOID(instance_p != NULL);
//     FT_ASSERTVOID(instance_p->is_ready == (u32)FT_COMPONENT_IS_READY);

//     /* This ISR will try to handle as many interrupts as it can in a single
// 	 * call. However, in most of the places where the user's error handler
//          * is called, this ISR exits because it is expected that the user will
//          * reset the device in nearly all instances.
// 	 */
//     reg_isr = FXMAC_READREG32(instance_p->config.base_address,
//                               FXMAC_ISR_OFFSET);

//     /* Read Transmit Q1 ISR */

//     regq1_isr = FXMAC_READREG32(instance_p->config.base_address,
//                                 FXMAC_INTQ1_STS_OFFSET);

//     /* Clear the interrupt status register */
//     FXMAC_WRITEREG32(instance_p->config.base_address, FXMAC_ISR_OFFSET,
//                      reg_isr);

//     /* Receive complete interrupt */
//     if ((reg_isr & FXMAC_IXR_FRAMERX_MASK) != 0x00000000U)
//     {
//         /* Clear RX status register RX complete indication but preserve
// 		 * error bits if there is any */
//         FXMAC_WRITEREG32(instance_p->config.base_address,
//                          FXMAC_RXSR_OFFSET,
//                          ((u32)FXMAC_RXSR_FRAMERX_MASK |
//                           (u32)FXMAC_RXSR_BUFFNA_MASK));
//         instance_p->recv_irq_handler(instance_p->recv_args);
//     }

//     /* Transmit Q1 complete interrupt */
//     if (((regq1_isr & FXMAC_INTQ1SR_TXCOMPL_MASK) != 0x00000000U))
//     {
//         /* Clear TX status register TX complete indication but preserve
// 		 * error bits if there is any */
//         FXMAC_WRITEREG32(instance_p->config.base_address,
//                          FXMAC_INTQ1_STS_OFFSET,
//                          FXMAC_INTQ1SR_TXCOMPL_MASK);
//         FXMAC_WRITEREG32(instance_p->config.base_address,
//                          FXMAC_TXSR_OFFSET,
//                          ((u32)FXMAC_TXSR_TXCOMPL_MASK |
//                           (u32)FXMAC_TXSR_USEDREAD_MASK));
//         instance_p->send_irq_handler(instance_p->send_args);
//     }

//     /* Transmit complete interrupt */
//     if ((reg_isr & FXMAC_IXR_TXCOMPL_MASK) != 0x00000000U)
//     {
//         /* Clear TX status register TX complete indication but preserve
// 		 * error bits if there is any */
//         FXMAC_WRITEREG32(instance_p->config.base_address,
//                          FXMAC_TXSR_OFFSET,
//                          ((u32)FXMAC_TXSR_TXCOMPL_MASK |
//                           (u32)FXMAC_TXSR_USEDREAD_MASK));
//         instance_p->send_irq_handler(instance_p->send_args);
//     }

//     /* Receive error conditions interrupt */
//     if ((reg_isr & FXMAC_IXR_RX_ERR_MASK) != 0x00000000U)
//     {
//         /* Clear RX status register */
//         reg_sr = FXMAC_READREG32(instance_p->config.base_address,
//                                  FXMAC_RXSR_OFFSET);
//         FXMAC_WRITEREG32(instance_p->config.base_address,
//                          FXMAC_RXSR_OFFSET, reg_sr);

//         /* Fix for CR # 692702. Write to bit 18 of net_ctrl
// 		 * register to flush a packet out of Rx SRAM upon
// 		 * an error for receive buffer not available. */
//         if ((reg_isr & FXMAC_IXR_RXUSED_MASK) != 0x00000000U)
//         {
//             reg_ctrl =
//                 FXMAC_READREG32(instance_p->config.base_address,
//                                 FXMAC_NWCTRL_OFFSET);
//             reg_ctrl |= (u32)FXMAC_NWCTRL_FLUSH_DPRAM_MASK;
//             FXMAC_WRITEREG32(instance_p->config.base_address,
//                              FXMAC_NWCTRL_OFFSET, reg_ctrl);
//         }

//         if (reg_sr != 0)
//         {
//             instance_p->error_irq_handler(instance_p->error_args,
//                                           FXMAC_RECV, reg_sr);
//         }
//     }

//     /* When FXMAC_IXR_TXCOMPL_MASK is flagged, FXmac_IXR_TXUSED_MASK
//          * will be asserted the same time.
//          * Have to distinguish this bit to handle the real error condition.
//          */
//     /* Transmit Q1 error conditions interrupt */
//     if (((regq1_isr & FXMAC_INTQ1SR_TXERR_MASK) != 0x00000000U) &&
//         ((regq1_isr & FXMAC_INTQ1SR_TXCOMPL_MASK) != 0x00000000U))
//     {
//         /* Clear Interrupt Q1 status register */
//         FXMAC_WRITEREG32(instance_p->config.base_address,
//                          FXMAC_INTQ1_STS_OFFSET, regq1_isr);
//         instance_p->error_irq_handler(instance_p->error_args, FXMAC_SEND,
//                                       regq1_isr);
//     }

//     /* Transmit error conditions interrupt */
//     if (((reg_isr & FXMAC_IXR_TX_ERR_MASK) != 0x00000000U) &&
//         (!(reg_isr & FXMAC_IXR_TXCOMPL_MASK) != 0x00000000U))
//     {
//         /* Clear TX status register */
//         reg_sr = FXMAC_READREG32(instance_p->config.base_address,
//                                  FXMAC_TXSR_OFFSET);
//         FXMAC_WRITEREG32(instance_p->config.base_address,
//                          FXMAC_TXSR_OFFSET, reg_sr);
//         instance_p->error_irq_handler(instance_p->error_args, FXMAC_SEND,
//                                       reg_sr);
//     }
// }

void FXmacQueueIntrHandler(s32 vector, void *args)
{
    u32 reg_isr;
    u32 reg_temp;
    u32 reg_ctrl;
    FXmac *instance_p = (FXmac *)args;
    FT_ASSERTVOID(instance_p != NULL);
    FT_ASSERTVOID(instance_p->is_ready == (u32)FT_COMPONENT_IS_READY);
    FT_ASSERTVOID((instance_p->config.tx_queue_id < FT_XMAC_QUEUE_MAX_NUM) && (instance_p->config.rx_queue_id < FT_XMAC_QUEUE_MAX_NUM))

    /* This ISR will try to handle as many interrupts as it can in a single
	 * call. However, in most of the places where the user's error handler
         * is called, this ISR exits because it is expected that the user will
         * reset the device in nearly all instances.
	 */

    if (vector == instance_p->config.queue_irq_num[instance_p->config.tx_queue_id])
    {
        /* queue0 uses legacy registers */
        if (instance_p->config.tx_queue_id == 0)
        {
            reg_isr = FXMAC_READREG32(instance_p->config.base_address,
                                      FXMAC_ISR_OFFSET);

            if ((reg_isr & FXMAC_IXR_TXCOMPL_MASK) != 0x00000000U)
            {
                /* Clear TX status register TX complete indication but preserve
		            * error bits if there is any */
                FXMAC_WRITEREG32(instance_p->config.base_address,
                                 FXMAC_TXSR_OFFSET,
                                 ((u32)FXMAC_TXSR_TXCOMPL_MASK |
                                  (u32)FXMAC_TXSR_USEDREAD_MASK));
                instance_p->send_irq_handler(instance_p->send_args);
            }

            /* Transmit error conditions interrupt */
            if (((reg_isr & FXMAC_IXR_TX_ERR_MASK) != 0x00000000U) &&
                (!(reg_isr & FXMAC_IXR_TXCOMPL_MASK) != 0x00000000U))
            {
                /* Clear TX status register */
                reg_temp = FXMAC_READREG32(instance_p->config.base_address,
                                           FXMAC_TXSR_OFFSET);
                FXMAC_WRITEREG32(instance_p->config.base_address,
                                 FXMAC_TXSR_OFFSET, reg_temp);
                instance_p->error_irq_handler(instance_p->error_args, FXMAC_SEND,
                                              reg_temp);
            }
        }
        else // use queue number more than 0
        {
            reg_isr = FXMAC_READREG32(instance_p->config.base_address,
                                      FXMAC_QUEUE_REGISTER_OFFSET(FXMAC_INTQ1_STS_OFFSET, instance_p->config.tx_queue_id));

            /* Transmit Q1 complete interrupt */
            if (((reg_isr & FXMAC_INTQUESR_TXCOMPL_MASK) != 0x00000000U))
            {
                /* Clear TX status register TX complete indication but preserve
		 * error bits if there is any */
                FXMAC_WRITEREG32(instance_p->config.base_address,
                                 FXMAC_QUEUE_REGISTER_OFFSET(FXMAC_INTQ1_STS_OFFSET, instance_p->config.tx_queue_id),
                                 FXMAC_INTQUESR_TXCOMPL_MASK);
                FXMAC_WRITEREG32(instance_p->config.base_address,
                                 FXMAC_TXSR_OFFSET,
                                 ((u32)FXMAC_TXSR_TXCOMPL_MASK |
                                  (u32)FXMAC_TXSR_USEDREAD_MASK));
                instance_p->send_irq_handler(instance_p->send_args);
            }

            /* Transmit Q1 error conditions interrupt */
            if (((reg_isr & FXMAC_INTQ1SR_TXERR_MASK) != 0x00000000U) &&
                ((reg_isr & FXMAC_INTQ1SR_TXCOMPL_MASK) != 0x00000000U))
            {
                /* Clear Interrupt Q1 status register */
                FXMAC_WRITEREG32(instance_p->config.base_address,
                                 FXMAC_QUEUE_REGISTER_OFFSET(FXMAC_INTQ1_STS_OFFSET, instance_p->config.tx_queue_id), reg_isr);
                instance_p->error_irq_handler(instance_p->error_args, FXMAC_SEND,
                                              reg_isr);
            }
        }
    }

    if (vector == instance_p->config.queue_irq_num[instance_p->config.rx_queue_id])
    {
        if (instance_p->config.rx_queue_id == 0)
        {
            reg_isr = FXMAC_READREG32(instance_p->config.base_address,
                                      FXMAC_ISR_OFFSET);

            /* Receive complete interrupt */
            if ((reg_isr & FXMAC_IXR_FRAMERX_MASK) != 0x00000000U)
            {
                /* Clear RX status register RX complete indication but preserve
		            * error bits if there is any */
                FXMAC_WRITEREG32(instance_p->config.base_address,
                                 FXMAC_RXSR_OFFSET,
                                 ((u32)FXMAC_RXSR_FRAMERX_MASK |
                                  (u32)FXMAC_RXSR_BUFFNA_MASK));
                instance_p->recv_irq_handler(instance_p->recv_args);
            }

            /* Receive error conditions interrupt */
            if ((reg_isr & FXMAC_IXR_RX_ERR_MASK) != 0x00000000U)
            {
                /* Clear RX status register */
                reg_temp = FXMAC_READREG32(instance_p->config.base_address,
                                           FXMAC_RXSR_OFFSET);
                FXMAC_WRITEREG32(instance_p->config.base_address,
                                 FXMAC_RXSR_OFFSET, reg_temp);

                /* Fix for CR # 692702. Write to bit 18 of net_ctrl
		 * register to flush a packet out of Rx SRAM upon
		 * an error for receive buffer not available. */
                if ((reg_isr & FXMAC_IXR_RXUSED_MASK) != 0x00000000U)
                {
                    reg_ctrl =
                        FXMAC_READREG32(instance_p->config.base_address,
                                        FXMAC_NWCTRL_OFFSET);
                    reg_ctrl |= (u32)FXMAC_NWCTRL_FLUSH_DPRAM_MASK;

                    FXMAC_WRITEREG32(instance_p->config.base_address,
                                     FXMAC_NWCTRL_OFFSET, reg_ctrl);
                }

                if (reg_temp != 0)
                {
                    instance_p->error_irq_handler(instance_p->error_args,
                                                  FXMAC_RECV, reg_temp);
                }
            }
        }
        else // use queue number more than 0
        {
            reg_isr = FXMAC_READREG32(instance_p->config.base_address,
                                      FXMAC_QUEUE_REGISTER_OFFSET(FXMAC_INTQ1_STS_OFFSET, instance_p->config.rx_queue_id));

            /* Receive complete interrupt */
            if ((reg_isr & FXMAC_INTQUESR_RCOMP_MASK) != 0x00000000U)
            {
                /* Clear RX status register RX complete indication but preserve
		            * error bits if there is any */
                FXMAC_WRITEREG32(instance_p->config.base_address,
                                 FXMAC_QUEUE_REGISTER_OFFSET(FXMAC_INTQ1_STS_OFFSET, instance_p->config.rx_queue_id),
                                 FXMAC_INTQUESR_RCOMP_MASK);
                instance_p->recv_irq_handler(instance_p->recv_args);
            }

            /* Receive error conditions interrupt */
            if ((reg_isr & FXMAC_IXR_RX_ERR_MASK) != 0x00000000U)
            {

                reg_ctrl =
                    FXMAC_READREG32(instance_p->config.base_address,
                                    FXMAC_NWCTRL_OFFSET);
                reg_ctrl &= ~(u32)FXMAC_NWCTRL_RXEN_MASK;

                FXMAC_WRITEREG32(instance_p->config.base_address,
                                 FXMAC_NWCTRL_OFFSET, reg_ctrl);

                /* Clear RX status register */
                reg_temp = FXMAC_READREG32(instance_p->config.base_address,
                                           FXMAC_RXSR_OFFSET);
                FXMAC_WRITEREG32(instance_p->config.base_address,
                                 FXMAC_RXSR_OFFSET, reg_temp);

                /* Fix for CR # 692702. Write to bit 18 of net_ctrl
		 * register to flush a packet out of Rx SRAM upon
		 * an error for receive buffer not available. */
                if ((reg_isr & FXMAC_IXR_RXUSED_MASK) != 0x00000000U)
                {
                    reg_ctrl =
                        FXMAC_READREG32(instance_p->config.base_address,
                                        FXMAC_NWCTRL_OFFSET);
                    reg_ctrl |= (u32)FXMAC_NWCTRL_FLUSH_DPRAM_MASK;

                    FXMAC_WRITEREG32(instance_p->config.base_address,
                                     FXMAC_NWCTRL_OFFSET, reg_ctrl);
                }

                /* Clear RX status register RX complete indication but preserve
		            * error bits if there is any */
                FXMAC_WRITEREG32(instance_p->config.base_address,
                                 FXMAC_QUEUE_REGISTER_OFFSET(FXMAC_INTQ1_STS_OFFSET, instance_p->config.rx_queue_id),
                                 FXMAC_INTQUESR_RXUBR_MASK);
                instance_p->recv_irq_handler(instance_p->recv_args);

                if (reg_temp != 0)
                {
                    instance_p->error_irq_handler(instance_p->error_args,
                                                  FXMAC_RECV, reg_temp);
                }
            }
        }
    }
}

// void FXmacIntrHandler(void *args)
// {
//     u32 reg_isr;
//     u32 reg_sr;
//     u32 reg_ctrl;
//     u32 regq1_isr = 0U;
//     FXmac *instance_p = (FXmac *)args;

//     FT_ASSERTVOID(instance_p != NULL);
//     FT_ASSERTVOID(instance_p->is_ready == (u32)FT_COMPONENT_IS_READY);

//     /* This ISR will try to handle as many interrupts as it can in a single
// 	 * call. However, in most of the places where the user's error handler
//          * is called, this ISR exits because it is expected that the user will
//          * reset the device in nearly all instances.
// 	 */
//     reg_isr = FXMAC_READREG32(instance_p->config.base_address,
//                               FXMAC_ISR_OFFSET);

//     /* Read Transmit Q1 ISR */

//     regq1_isr = FXMAC_READREG32(instance_p->config.base_address,
//                                 FXMAC_INTQ1_STS_OFFSET);

//     /* Clear the interrupt status register */
//     FXMAC_WRITEREG32(instance_p->config.base_address, FXMAC_ISR_OFFSET,
//                      reg_isr);

//     /* Receive complete interrupt */
//     if ((reg_isr & FXMAC_IXR_FRAMERX_MASK) != 0x00000000U)
//     {
//         /* Clear RX status register RX complete indication but preserve
// 		 * error bits if there is any */
//         FXMAC_WRITEREG32(instance_p->config.base_address,
//                          FXMAC_RXSR_OFFSET,
//                          ((u32)FXMAC_RXSR_FRAMERX_MASK |
//                           (u32)FXMAC_RXSR_BUFFNA_MASK));
//         instance_p->recv_irq_handler(instance_p->recv_args);
//     }

//     /* Transmit Q1 complete interrupt */
//     if (((regq1_isr & FXMAC_INTQ1SR_TXCOMPL_MASK) != 0x00000000U))
//     {
//         /* Clear TX status register TX complete indication but preserve
// 		 * error bits if there is any */
//         FXMAC_WRITEREG32(instance_p->config.base_address,
//                          FXMAC_INTQ1_STS_OFFSET,
//                          FXMAC_INTQ1SR_TXCOMPL_MASK);
//         FXMAC_WRITEREG32(instance_p->config.base_address,
//                          FXMAC_TXSR_OFFSET,
//                          ((u32)FXMAC_TXSR_TXCOMPL_MASK |
//                           (u32)FXMAC_TXSR_USEDREAD_MASK));
//         instance_p->send_irq_handler(instance_p->send_args);
//     }

//     /* Transmit complete interrupt */
//     if ((reg_isr & FXMAC_IXR_TXCOMPL_MASK) != 0x00000000U)
//     {
//         /* Clear TX status register TX complete indication but preserve
// 		 * error bits if there is any */
//         FXMAC_WRITEREG32(instance_p->config.base_address,
//                          FXMAC_TXSR_OFFSET,
//                          ((u32)FXMAC_TXSR_TXCOMPL_MASK |
//                           (u32)FXMAC_TXSR_USEDREAD_MASK));
//         instance_p->send_irq_handler(instance_p->send_args);
//     }

//     /* Receive error conditions interrupt */
//     if ((reg_isr & FXMAC_IXR_RX_ERR_MASK) != 0x00000000U)
//     {
//         /* Clear RX status register */
//         reg_sr = FXMAC_READREG32(instance_p->config.base_address,
//                                  FXMAC_RXSR_OFFSET);
//         FXMAC_WRITEREG32(instance_p->config.base_address,
//                          FXMAC_RXSR_OFFSET, reg_sr);

//         /* Fix for CR # 692702. Write to bit 18 of net_ctrl
// 		 * register to flush a packet out of Rx SRAM upon
// 		 * an error for receive buffer not available. */
//         if ((reg_isr & FXMAC_IXR_RXUSED_MASK) != 0x00000000U)
//         {
//             reg_ctrl =
//                 FXMAC_READREG32(instance_p->config.base_address,
//                                 FXMAC_NWCTRL_OFFSET);
//             reg_ctrl |= (u32)FXMAC_NWCTRL_FLUSH_DPRAM_MASK;
//             FXMAC_WRITEREG32(instance_p->config.base_address,
//                              FXMAC_NWCTRL_OFFSET, reg_ctrl);
//         }

//         if (reg_sr != 0)
//         {
//             instance_p->error_irq_handler(instance_p->error_args,
//                                           FXMAC_RECV, reg_sr);
//         }
//     }

//     /* When FXMAC_IXR_TXCOMPL_MASK is flagged, FXmac_IXR_TXUSED_MASK
//          * will be asserted the same time.
//          * Have to distinguish this bit to handle the real error condition.
//          */
//     /* Transmit Q1 error conditions interrupt */
//     if (((regq1_isr & FXMAC_INTQ1SR_TXERR_MASK) != 0x00000000U) &&
//         ((regq1_isr & FXMAC_INTQ1SR_TXCOMPL_MASK) != 0x00000000U))
//     {
//         /* Clear Interrupt Q1 status register */
//         FXMAC_WRITEREG32(instance_p->config.base_address,
//                          FXMAC_INTQ1_STS_OFFSET, regq1_isr);
//         instance_p->error_irq_handler(instance_p->error_args, FXMAC_SEND,
//                                       regq1_isr);
//     }

//     /* Transmit error conditions interrupt */
//     if (((reg_isr & FXMAC_IXR_TX_ERR_MASK) != 0x00000000U) &&
//         (!(reg_isr & FXMAC_IXR_TXCOMPL_MASK) != 0x00000000U))
//     {
//         /* Clear TX status register */
//         reg_sr = FXMAC_READREG32(instance_p->config.base_address,
//                                  FXMAC_TXSR_OFFSET);
//         FXMAC_WRITEREG32(instance_p->config.base_address,
//                          FXMAC_TXSR_OFFSET, reg_sr);
//         instance_p->error_irq_handler(instance_p->error_args, FXMAC_SEND,
//                                       reg_sr);
//     }
// }

/** @} */